package com.flyme.module.base.provider.service.impl;


import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.flyme.common.core.constants.CommonConstants;
import com.flyme.common.core.exception.OpenMessageException;
import com.flyme.common.core.model.query.CriteriaQuery;
import com.flyme.common.core.utils.*;
import com.flyme.core.base.supper.service.impl.BaseServiceImpl;
import com.flyme.module.base.client.constants.BaseConstants;
import com.flyme.module.base.client.dto.SysAccountDto;
import com.flyme.module.base.client.dto.SysThirdLogin;
import com.flyme.module.base.client.dto.SysUserDto;
import com.flyme.module.base.client.entity.*;
import com.flyme.module.base.provider.mapper.SysAccountMapper;
import com.flyme.module.base.provider.service.*;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * @author zyf
 */
@Slf4j
@Service
@Transactional(rollbackFor = Exception.class)
public class SysAccountServiceImpl extends BaseServiceImpl<SysAccountMapper, SystemAccount> implements SysAccountService {


    @Autowired
    private SysAccountLogsService accountLogsService;
    @Autowired
    private SysUserService userService;
    @Autowired
    private PasswordEncoder passwordEncoder;
    @Autowired
    private SysRoleService roleService;
    @Autowired
    private SysAuthorizeService accessService;
    @Autowired
    private SysCompanyService companyService;


    /**
     * 添加系统用户
     *
     * @param userDto
     * @return
     */
    @Override
    public Boolean register(SysUserDto userDto) {
        String userName = userDto.getUserName();
        ApiAssert.notNull("账号不能为空", userName);
        String password = userDto.getPassword();
        ApiAssert.notNull("密码不能为空!", password);
        String mobile = userDto.getMobile();
        if(ObjectUtils.isNotEmpty(mobile)){
            SysUser saved = userService.findByUserName(mobile);
            ApiAssert.isNull("手机号已占用", saved);
        }
        if(ObjectUtils.isNotEmpty(userName)){
            SysUser saved = userService.findByUserName(userName);
            ApiAssert.isNull("用户名已占用", saved);
        }
        //未注册
        SysUser saved = new SysUser();
        BeanUtils.copyProperties(userDto, saved);
        //加密
        String encodePassword = passwordEncoder.encode(password);
        saved.setStatus(CommonConstants.ENABLED);
        saved.setSchoolRegister("0");
        Boolean tag = userService.save(saved);
        //注册账户且账户不是手机号
        if (ObjectUtils.isNotEmpty(userName) && !StringUtils.matchMobile(userName) && ObjectUtils.isEmpty(mobile)) {
            this.registerUsernameAccount(saved.getId(), saved.getUserName(), encodePassword);
        }
        //注册email账号登陆
        if (StringUtils.isNotBlank(saved.getEmail())) {
            this.registerMobileAccount(saved.getId(), saved.getEmail(), encodePassword);
        }
        //注册手机号账号登陆
        if (StringUtils.isNotBlank(saved.getMobile())) {
            this.registerMobileAccount(saved.getId(), saved.getMobile(), encodePassword);
        }
        if (ObjectUtils.isNotEmpty(userDto.getRoleIds())) {
            //添加账户角色
            roleService.saveUserRoles(saved.getId(), userDto.getRoleIds());
        }
        if (ObjectUtils.isNotEmpty(userDto.getRoleCode())) {
            //添加账户角色
            roleService.saveUserRoles(saved.getId(), userDto.getRoleCode());
        }
        return tag;
    }


    /**
     * 第三方登录(第一步创建登录账户)
     *
     * @param thirdLogin
     */
    public SystemAccount registerByThird(SysThirdLogin thirdLogin) {
        SystemAccount systemAccount = getOne(q().eq("account", thirdLogin.getIdentifier()));
        if (ObjectUtils.isEmpty(systemAccount)) {
            String encodePassword = passwordEncoder.encode(CommonConstants.DEF_PWD);
            systemAccount = new SystemAccount(thirdLogin.getUserId(), thirdLogin.getIdentifier(), encodePassword, thirdLogin.getLoginType(), BaseConstants.USER_STATE_NORMAL, thirdLogin.getNickname(), thirdLogin.getUserhead());
            save(systemAccount);
        }
        return systemAccount;
    }

    /**
     * 绑定账户
     *
     * @param thirdLogin
     */
    public Boolean bind(SysThirdLogin thirdLogin) {
        Boolean isBind = false;
        SystemAccount systemAccount = getOne(q().eq("account", thirdLogin.getIdentifier()));
        if (ObjectUtils.isEmpty(systemAccount)) {
            String encodePassword = passwordEncoder.encode(CommonConstants.DEF_PWD);
            systemAccount = new SystemAccount(thirdLogin.getUserId(), thirdLogin.getIdentifier(), encodePassword, thirdLogin.getLoginType(), BaseConstants.USER_STATE_NORMAL, thirdLogin.getNickname(), thirdLogin.getUserhead());
            save(systemAccount);
            isBind = true;
        }
        return isBind;
    }

    /**
     * 第三方登录(第二步綁定手机号)
     */
    @Override
    public Boolean bingMobile(String userType, String accountId, String mobile) {
        SysUser sysUser = userService.findByMobile(mobile);
        if (ObjectUtils.isEmpty(sysUser)) {
            SystemAccount account = getById(accountId);
            sysUser = new SysUser();
            sysUser.setUserType(userType);
            sysUser.setMobile(mobile);
            sysUser.setStatus(CommonConstants.ENABLED);
            sysUser.setNickName(account.getNickName());
            sysUser.setAvatar("https://s1.ax1x.com/2018/05/19/CcdVQP.png");
            userService.save(sysUser);
            String encodePassword = passwordEncoder.encode(CommonConstants.DEF_PWD);
            this.registerMobileAccount(sysUser.getId(), mobile, encodePassword);
        }
        UpdateWrapper u = new UpdateWrapper();
        return update(u.set(true, "userId", sysUser.getId()).eq(true, "id", accountId));
    }

    /**
     * 支持系统用户名、手机号、email登陆
     *
     * @param account
     * @return
     */
    @Override
    public SysAccountDto login(String account) {
        if (StringUtils.isBlank(account)) {
            return null;
        }
        SystemAccount systemAccount = null;
        SysAccountDto systemAccountDto = null;
      /*  //默认用户名登录
        String accountType = BaseConstants.USER_ACCOUNT_TYPE_USERNAME;
        if (systemAccount == null && StringUtils.matchMobile(account)) {
            accountType = BaseConstants.USER_ACCOUNT_TYPE_MOBILE;
        }
        if (systemAccount == null && StringUtils.matchEmail(account)) {
            accountType = BaseConstants.USER_ACCOUNT_TYPE_EMAIL;
        }*/
        systemAccount = getOne(q().eq("account", account));
        if (systemAccount != null) {
            List<String> authorities = Lists.newArrayList();
            List<Map> roles = Lists.newArrayList();
            //查询角色权限
            List<SystemRole> rolesList = roleService.getUserRoles(systemAccount.getUserId());
            if (ObjectUtils.isNotEmpty(rolesList)) {
                for (SystemRole role : rolesList) {
                    authorities.add(BaseConstants.AUTHORITY_PREFIX_ROLE + role.getRoleCode());
                    Map map = Maps.newHashMap();
                    map.put("code", role.getRoleCode());
                    map.put("name", role.getRoleName());
                    roles.add(map);
                }
            } else {
                //給APP用戶设置权限
                authorities.add(BaseConstants.AUTHORITY_PREFIX_APP + "USER");
            }
            //获取系统用户私有权限
            List<SysAuthority> userAccessList = accessService.getUserPrivateGrantAccessList(systemAccount.getUserId());
            if (userAccessList != null) {
                for (SysAuthority access : userAccessList) {
                    authorities.add(access.getAuthority());
                }
            }
            //查询系统用户资料
            SysUser systemUser = userService.getById(systemAccount.getUserId());
            SysUserDto userProfile = new SysUserDto();
            userProfile.setSchoolRegister("0");//未申请状态
            Long companyId = systemUser.getCompanyId();
            if (ObjectUtils.isNotEmpty(companyId)) {
                SysCompany company = companyService.getById(companyId);
                systemUser.setCompany(company.getCompName());
            }
            BeanUtils.copyProperties(systemUser, userProfile);
            //设置用户资料,权限信息
            userProfile.setAuthorities(authorities);
            userProfile.setRoles(roles);
            systemAccountDto = new SysAccountDto();
            BeanUtils.copyProperties(systemAccount, systemAccountDto);
            systemAccountDto.setUserProfile(userProfile);
            //添加登录日志
            try {
                HttpServletRequest request = WebUtils.getHttpServletRequest();
                if (request != null) {
                    SystemAccountLogs log = new SystemAccountLogs();
                    log.setUserId(systemAccount.getUserId());
                    log.setAccount(systemAccount.getAccount());
                    log.setAccountType(systemAccount.getAccountType());
                    //log.setLoginIp(WebUtils.getIpAddr(request));
                    log.setLoginAgent(request.getHeader(HttpHeaders.USER_AGENT));
                    addLoginLog(log);
                }
            } catch (Exception e) {
                log.error("添加登录日志失败");
            }
        }
        return systemAccountDto;
    }

    /**
     * 注册系统用户名账户
     *
     * @param userId
     * @param username
     * @param password
     */
    @Override
    public Boolean registerUsernameAccount(Long userId, String username, String password) {
        if (isExist(username, BaseConstants.USER_ACCOUNT_TYPE_USERNAME)) {
            //已经注册
            return false;
        }
        SystemAccount systemAccount = new SystemAccount(userId, username, password, BaseConstants.USER_ACCOUNT_TYPE_USERNAME, BaseConstants.USER_STATE_NORMAL, null, null);
        return save(systemAccount);
    }

    /**
     * 注册email账号
     *
     * @param userId
     * @param email
     * @param password
     */
    @Override
    public Boolean registerEmailAccount(Long userId, String email, String password) {
       /* if (!StringUtils.matchEmail(email)) {
            return false;
        }*/
        if (isExist(email, BaseConstants.USER_ACCOUNT_TYPE_EMAIL)) {
            //已经注册
            return false;
        }
        SystemAccount systemAccount = new SystemAccount(userId, email, password, BaseConstants.USER_ACCOUNT_TYPE_EMAIL, BaseConstants.USER_STATE_NORMAL, null, null);
        return save(systemAccount);
    }

    /**
     * 注册手机账号
     *
     * @param userId
     * @param mobile
     * @param password
     */
    @Override
    public Boolean registerMobileAccount(Long userId, String mobile, String password) {
        if (!StringUtils.matchMobile(mobile)) {
            return false;
        }
        if (isExist(mobile, BaseConstants.USER_ACCOUNT_TYPE_MOBILE)) {
            //已经注册
            return false;
        }
        SystemAccount systemAccount = new SystemAccount(userId, mobile, password, BaseConstants.USER_ACCOUNT_TYPE_MOBILE, BaseConstants.USER_STATE_NORMAL, null, null);
        return save(systemAccount);
    }

    /**
     * 更新系统用户密码
     *
     * @param userId
     * @param oldPassword
     * @param newPassword
     * @return
     */
    @Override
    public Boolean resetPassword(Long userId, String oldPassword, String newPassword) {
        if (userId == null || StringUtils.isBlank(oldPassword) || StringUtils.isBlank(newPassword)) {
            return false;
        }
        SysUser userProfile = userService.getById(userId);
        if (userProfile == null) {
            throw new OpenMessageException("系统用户不存在");
        }
        SystemAccount systemAccount = getOne(q().eq("userId", userId).eq("account", userProfile.getUserName()).eq("accountType", BaseConstants.USER_ACCOUNT_TYPE_USERNAME));
        if (systemAccount == null) {
            return false;
        }
        if (!passwordEncoder.matches(oldPassword, systemAccount.getPassword())) {
            throw new OpenMessageException("原密码不正确");
        }
        systemAccount.setPassword(passwordEncoder.encode(newPassword));
        return saveOrUpdate(systemAccount);
    }

    /**
     * 更新系统用户密码
     *
     * @param
     * @param
     * @param newPassword
     * @return
     */
    @Override
    public Boolean resetOtherPwd(String account, String newPassword) {
        UpdateWrapper updateWrapper = new UpdateWrapper();
        return update(updateWrapper.set(true, "password", passwordEncoder.encode(newPassword)).eq(true, "account", account));
    }

    /**
     * 更新系统用户登录Ip
     *
     * @param log
     */
    @Override
    public void addLoginLog(SystemAccountLogs log) {
        CriteriaQuery cq = new CriteriaQuery<SystemAccountLogs>();
        int count = accountLogsService.count(cq.eq("userId", log.getUserId()));
        log.setLoginTime(new Date());
        log.setLoginNums(count + 1);
        accountLogsService.save(log);
    }


    /**
     * 检查账户类型是否存在
     *
     * @param userId
     * @param accountType
     * @return
     */
    @Override
    public Boolean isExist(Long userId, String accountType) {
        int count = count(q().eq("userId", userId).eq("accountType", accountType));
        return count > 0 ? true : false;
    }

    /**
     * 检查账户类型是否存在
     *
     * @param userId
     * @param accountType
     * @return
     */
    @Override
    public SystemAccount get(Long userId, String accountType) {
        return getOne(q().eq("userId", userId).eq("accountType", accountType));
    }

    /**
     * 检查是否已注册账号
     *
     * @param account
     * @param accountType
     * @return
     */
    public Boolean isExist(String account, String accountType) {
        int count = count(q().eq("account", account).eq("accountType", accountType));
        return count > 0 ? true : false;
    }

    /**
     * 解绑email账号
     *
     * @param userId
     * @param email
     * @return
     */
    @Override
    public Boolean removeEmailAccount(Long userId, String email) {
        return remove(q().eq("userId", userId).eq("acount", email).eq("accountType", BaseConstants.USER_ACCOUNT_TYPE_EMAIL));
    }

    /**
     * 解绑手机账号
     *
     * @param userId
     * @param mobile
     * @return
     */
    @Override
    public Boolean removeMobileAccount(Long userId, String mobile) {
        return remove(q().eq("userId", userId).eq("acount", mobile).eq("accountType", BaseConstants.USER_ACCOUNT_TYPE_MOBILE));
    }

    @Override
    public Boolean deleteByIds(Long[] ids) {
        ApiAssert.notNull("参数不能为空", ids);
        CriteriaQuery qw = new CriteriaQuery();
        qw.in("userId", ids);
        return remove(qw);
    }

    /**
     * 根据用户id及手机号查询账户
     */
    public SystemAccount findByUser(Long userId, String mobile) {
        return getOne(q().eq("userId", userId).eq("account", mobile));
    }


    /**
     * 根据账户名查询
     *
     * @param accountName
     * @return
     */
    @Override
    public SystemAccount findByAccount(String accountName) {
        return getOne(q().eq("account", accountName));
    }
}
